import bcrypt from 'bcrypt'
import crypto from 'crypto'
import jwt from 'jsonwebtoken'

export function md5(password, salt = '') {
    const md5obj = crypto.createHash('md5')
    if (salt)
        md5obj.update(salt)
    md5obj.update(password)
    return md5obj.digest('hex')
}

export function parseTime(time, cFormat) {
    if (arguments.length === 0 || !time) {
        return null
    }
    const format = cFormat || '{y}-{m}-{d} {h}:{i}:{s}'
    let date
    if (typeof time === 'object') {
        date = time
    } else {
        if ((typeof time === 'string')) {
        if ((/^[0-9]+$/.test(time))) {
            // support "1548221490638"
            time = parseInt(time)
        } else {
            // support safari
            // https://stackoverflow.com/questions/4310953/invalid-date-in-safari
            time = time.replace(new RegExp(/-/gm), '/')
        }
        }

        if ((typeof time === 'number') && (time.toString().length === 10)) {
        time = time * 1000
        }
        date = new Date(time)
    }
    const formatObj = {
        y: date.getFullYear(),
        m: date.getMonth() + 1,
        d: date.getDate(),
        h: date.getHours(),
        i: date.getMinutes(),
        s: date.getSeconds(),
        a: date.getDay()
    }
    const time_str = format.replace(/{([ymdhisa])+}/g, (result, key) => {
        const value = formatObj[key]
        // Note: getDay() returns 0 on Sunday
        if (key === 'a') { return ['日', '一', '二', '三', '四', '五', '六'][value ] }
        return value.toString().padStart(2, '0')
    })
    return time_str
}

export function findMembers(instance, {
    prefix,
    specifiedType,
    filter
  }) {
    // 递归函数
    function _find(instance) {
      //基线条件（跳出递归）
      if (instance.__proto__ === null)
        return []
  
      let names = Reflect.ownKeys(instance)
      names = names.filter((name) => {
        // 过滤掉不满足条件的属性或方法名
        return _shouldKeep(name)
      })
  
      return [...names, ..._find(instance.__proto__)]
    }
  
    function _shouldKeep(value) {
      if (filter) {
        if (filter(value)) {
          return true
        }
      }
      if (prefix)
        if (value.startsWith(prefix))
          return true
      if (specifiedType)
        if (instance[value] instanceof specifiedType)
          return true
    }
  
    return _find(instance)
  }

export function getEncryptPassword(password, salt = '') {
  return md5(md5(password) + salt)
}
  
  // 颁布令牌
export function generateToken(uid, scope) {
  const secretKey = global.config.security.secretKey;
  const expiresIn = global.config.security.expiresIn;
  const token = jwt.sign({
    uid,
    scope
  }, secretKey, {
    expiresIn: expiresIn
  })
  return token
}

export async function hashPassword(password) {
  try {
    // 使用 bcrypt.hash() 生成密码的哈希
    const hashedPassword = await bcrypt.hash(password, 10)
    return hashedPassword
  } catch (error) {
    console.error('哈希密码失败:', error)
  }
}

export async function verifyPassword(inputPassword, storedHash) {
  try {
    // 使用 bcrypt.compare() 来验证密码是否匹配
    const isMatch = await bcrypt.compare(inputPassword, storedHash)
    if (isMatch) {
      return true
    } else {
      return false
    }
  } catch (error) {
    console.error('密码验证失败:', error)
  }
}

export function isUrl(str) {
  try {
    new URL(str)
    return true
  } catch (e) {
    return false
  }
}

export function handleTreeList(arr, pid = 0, depth = 0, pSub = 'parent_id', cSub = 'children', dSub = 'depth') {
  const returnArray = [];
  
  if (Array.isArray(arr) && arr.length > 0) {
    // 使用 slice 和 filter 保留当前处理的节点，不修改原数组
    const filteredArr = arr.filter(v => v[pSub] === pid);
    
    filteredArr.forEach((v) => {
      // 设置当前节点的深度
      v[dSub] = depth;

      // 创建临时节点
      const tempInfo = { ...v };

      // 递归处理子节点
      const temp = handleTreeList(arr, v.id, depth + 1, pSub, cSub, dSub);

      if (temp.length > 0) {
        // 如果有子节点
        tempInfo.component = pid === 0 ? 'Layout' : 'views/' + v.view;
        tempInfo.redirect = temp[0].path;
        tempInfo[cSub] = temp;
      } else {
        // 如果没有子节点
        tempInfo.component = 'views/' + v.view;
        if (!isUrl(v.path)) {
          tempInfo.path = '/' + v.view;
        }
        tempInfo[cSub] = temp;
      }

      returnArray.push(tempInfo);
    });
  }

  return returnArray;
}

